package com.hsmpay.utils;

import it.sauronsoftware.base64.Base64;
import org.apache.log4j.Logger;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;

/**
 * 3DES加密工具类
 * @date 2014-04-17
 */
public class Des3 {
	static Logger log = Logger.getLogger(Des3.class);
	// 密钥
	private final static String secretKey = "zhongyi@163.com$#6688#$";
	// 向量
	private final static String iv = "87654321";
	// 加解密统一使用的编码方式
	private final static String encoding = "utf-8";

    private final static String XPDESKEY = "4068A376E6BC6B2EFBD74046FF6C0B6A";

	/**
	 * 3DES加密
	 * @param plainText 普通文本
	 * @param secretKey
	 * @return
	 * @throws Exception 
	 */
	public static String encode(String plainText,String secretKey){
		try{
			Key deskey = null;
			DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
			SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
			deskey = keyfactory.generateSecret(spec);
	
			Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
			IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
			cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
			byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding));
			//return Des3Base64.encode(encryptData);
			byte[] bb = Base64.encode(encryptData);
			return new String(bb,"UTF-8");
		}catch(Exception e){
			e.printStackTrace();
		}
		return plainText;
	}

	/**
	 * 3DES加密
	 * @param plainText 普通文本
	 * @return
	 * @throws Exception 
	 */
	public static String encode(String plainText){
		return encode(plainText,secretKey);
	}

	/**
	 * 3DES解密
	 * 
	 * @param encryptText 加密文本
	 * @return
	 * @throws Exception
	 */
	public static String decode(String encryptText,String secretKey){
		try{
			Key deskey = null;
			DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
			SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
			deskey = keyfactory.generateSecret(spec);
			Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
			IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
			cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
            byte[] decryptData = cipher.doFinal(Base64.decode(encryptText.getBytes("UTF-8")));
			return new String(decryptData, encoding);
		}catch(Exception e){
			e.printStackTrace();
		}
		return encryptText;
	}
	
	/**
	 * 3DES解密
	 * 
	 * @param encryptText 加密文本
	 * @return
	 * @throws Exception
	 */
	public static String decode(String encryptText){
		return decode(encryptText,secretKey);
	}

	/**
	 * 生成8位DES密钥  转码的16位密钥
	 * @return
	 */
	public static String generate16Key(){
		KeyGenerator kg;
		try {
			kg = KeyGenerator.getInstance("DES");
			kg.init(56);
			SecretKey secretKey = kg.generateKey();
			byte[] key = secretKey.getEncoded();
			return byte2hex(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 转换成十六进制字符串
	 * @param b
	 * @return
	 */
    public static String byte2hex(byte[] b) {
        String hs="";
        String stmp="";

        for (int n=0;n<b.length;n++) {
            stmp=(Integer.toHexString(b[n] & 0XFF));
            if (stmp.length()==1) 
            	hs=hs+"0"+stmp;
            else 
            	hs=hs+stmp;
            //if (n<b.length-1)  hs=hs+":";
        }
        return hs.toUpperCase();
    }
    
	/**
	 * 生成8位DES密钥  转码的32位密钥
	 * @return
	 */
	public static String generate32Key(){
		return MD5.mD5ofStr(generate16Key());
	}
	
	public static byte[] hexStringToByte(String hex) {
		hex=hex.toUpperCase();
		int len = (hex.length() / 2);
		byte[] result = new byte[len];
		char[] achar = hex.toCharArray();
		for (int i = 0; i < len; i++) {
			int pos = i * 2;
			result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
		}
		return result;
	}
	
	private static byte toByte(char c) {
		byte b = (byte) "0123456789ABCDEF".indexOf(c);
		return b;
	}
	

	/**
	 * 3DES解密
	 * @param dataS 解密数据
	 * @return keys 密钥
	 */
	public static String decode3DES(String dataS, String keys)throws Exception{
		String result="";
		 try {
			 	byte[] data=hexStringToByte(dataS);
			 	byte[] key=hexStringToByte(keys);
				byte[] km = new byte[24];
				System.arraycopy(key, 0, km, 0, 16);
				System.arraycopy(key, 0, km, 16, 8);
				Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
				DESedeKeySpec dks = new DESedeKeySpec(km);
				SecretKey k = SecretKeyFactory.getInstance("DESede")
						.generateSecret(dks);
				cipher.init(Cipher.DECRYPT_MODE, k);
				result=byte2hex(cipher.doFinal(data));
			} catch (Exception e) {
				e.printStackTrace();
				throw new Exception(e);
			}
			return result;
	 }
	/**
	 * 3DES加密
	 * @param key 密钥
	 * @param data 待加密数据
	 * @return byte[] 加密数据
	 */
	public static byte[] encode3DES(byte[] key, byte[] data) throws Exception{
		try {
			byte[] km = new byte[24];
			System.arraycopy(key, 0, km, 0, 16);
			System.arraycopy(key, 0, km, 16, 8);
			Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
			DESedeKeySpec dks = new DESedeKeySpec(km);
			SecretKey k = SecretKeyFactory.getInstance("DESede")
					.generateSecret(dks);
			cipher.init(Cipher.ENCRYPT_MODE, k);
			byte[] result = cipher.doFinal(data);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception(e);
		}
	}
	
	/**
	 * 3DES加密
	 * @param keys 密钥
	 * @param dataS 待加密数据
	 * @return keys 加密数据
	 */
	public static String encode3DES(String dataS, String keys) throws Exception{
		byte[] data=hexStringToByte(dataS);
	 	byte[] key=hexStringToByte(keys);
	 	String result = byte2hex(encode3DES(key, data));
	 	return result;
	}

	/**
	 * DES解密
	 * @param myinfo
	 * @param key
	 * @return
	 */
	public static byte[] decodc(byte[] myinfo,byte[] key)throws Exception {
		String Algorithm = "DES"; //DES,DESede,Blowfish
		try {
			DESKeySpec dks = new DESKeySpec(key);

			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm);
			SecretKey deskey = keyFactory.generateSecret(dks);

			//log.debug("解密前数据=[" + byte2hex(myinfo)+"]");

			Cipher c1 = Cipher.getInstance("DES/ECB/NoPadding");
			c1.init(Cipher.DECRYPT_MODE, deskey);

			byte[] cipherByte = c1.doFinal(myinfo);
			//log.debug("解密结果=[" + byte2hex(cipherByte)+"]");
			return cipherByte;

		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
	}
	
	/**
	 * DES加密
	 * @param myinfo
	 * @param key
	 * @return
	 */
	public static byte[] encodc(byte[] myinfo,byte[] key)throws Exception{
		// Security.addProvider(new com.sun.crypto.provider.SunJCE());
		String Algorithm = "DES"; //DES,DESede,Blowfish
		try {
			DESKeySpec dks = new DESKeySpec(key);

			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm);
			SecretKey deskey = keyFactory.generateSecret(dks);
			//log.debug("加密前数据=[" + byte2hex(myinfo)+"]");
			Cipher c1 = Cipher.getInstance("DES/ECB/NoPadding");
			//Cipher c1 = Cipher.getInstance("DES");
			c1.init(Cipher.ENCRYPT_MODE, deskey);
			byte[] cipherByte = c1.doFinal(myinfo);
			//log.debug("加密结果=[" + byte2hex(cipherByte)+"]");
			return cipherByte;

		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
	}
	
	//异或
	public static byte[] XORContent( byte[] content1,byte[] content2 ){
	   int i=0;
	   int len = content1.length;
	   //byte []sOutMAC =new byte[8];
	   byte[] res=new byte[len];
	   for( i=0; i<len; i++){
		   res[i]=(byte) (content1[i]^content2[i]);
	   }
	   return res;
	   
	}
	
	/**
	 * 转成十六进制数字
	 * @param n
	 * @return
	 */
	public static String Int2HexStr(int n){
		String HexStr=Integer.toHexString(n);
		HexStr=HexStr.length()==1?"0"+HexStr:HexStr;
		return HexStr;
	}
	
	public static byte[] getDESKey(String hexKey){
		String strKey=hexKey.toUpperCase();
		return hexStringToByte(strKey);
	}
	
	/**
	 * PIN加密
	 * @param Pan 卡号
	 * @param Pin 密码
	 * @param PinKey 密码密钥
	 * @return
	 */
	public static String encryptPin(String Pan,String Pin,String PinKey)throws Exception{
		String DesPin="";
		try{
			Pan=Pan.substring(Pan.length()-13, Pan.length()-1);
			int PanLen=Pan.length();
			for(int i=0;i<16-PanLen;i++)
			{
				Pan="0"+Pan;
			}
			Pin=Int2HexStr(Pin.length())+Pin;
			int PinLen=Pin.length();
			for(int j=0;j<16-PinLen;j++)
			{
				Pin+="F";
			}
			byte[] res=XORContent(hexStringToByte(Pin),hexStringToByte(Pan));
			log.debug("异或数据=["+Pan+"]["+Pin+"]");
			log.debug("异或的结果=["+byte2hex(res)+"]");
			if(PinKey.length()==32)
			{
				log.debug("=====加密开始========");
				log.debug("加密数据=["+byte2hex(res)+"]["+PinKey+"]");
				byte[] res1=encode3DES(getDESKey(PinKey),res);
				DesPin=byte2hex(res1);
				log.debug("加密的结果=["+DesPin+"]");
				log.debug("=====加密结束========");
			}else{
				log.debug("=====加密开始========");
				log.debug("加密数据=["+byte2hex(res)+"]["+PinKey+"]");
				byte[] res1=encodc(res,getDESKey(PinKey));
				DesPin=byte2hex(res1);
				log.debug("加密的结果=["+DesPin+"]");
				log.debug("=====加密结束========");
			}
		}catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		return DesPin;
	}
	
	/**
	 * 二磁道加密
	 * @param trkKey
	 * @param track
	 * @return
	 */
	public static String encryptStanderTranck(String trkKey,String track)throws Exception{	
		log.debug("trkKey:"+trkKey);
		int trkLen=track.length();
		//track=Int2HexStr(trkLen)+track;
		int mod=trkLen%16;
		log.debug("mod:"+mod);
		for(int i=0;i<16-mod;i++)
		{
			track+="F";
		}
		
		String mTrack="";
		try {
			log.debug("track:"+track);
			mTrack=byte2hex(encode3DES(hexStringToByte(trkKey),hexStringToByte(track)));
			mTrack=Int2HexStr(trkLen)+mTrack;
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		
		return mTrack;
	}

    /**
     * 小票路径3DES加密
     * @param plainText 普通文本
     * @return
     * @throws Exception
     */
    public static String encodeXP(String plainText){
        int length = plainText.length();
        String req = plainText.replace("_","A");
        String result = "";
        if(length%8 != 0){
            int aa = length%8;
            int bb = 8-aa;
            StringBuilder sbr = new StringBuilder();
            for(int i=0;i<bb;i++){
                sbr.append("F");
            }
            result = req+sbr.toString();

        }else {
            result = req;
        }
        String val = null;
        try {
            val = encode3DES(result, XPDESKEY);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return val;
    }

    /**
     * 小票路径3DES解密
     *
     * @param encryptText 加密文本
     * @return
     * @throws Exception
     */
    public static String decodeXP(String encryptText){
        String input = null;
        try {
            input = decode3DES(encryptText, XPDESKEY);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return input.substring(0,input.indexOf("F")).toString().replace("A","_");
    }

//	public static void main(String[] args) throws Exception {
		
//		String PinKey="E3D13ACC2EC98480039FE9F955961CC0";
//		String Pin="123456";
//		String Pan = "6226220286298871";
//		String desPin = encryptPin(Pan, Pin, PinKey);
//		log.debug("desPin = "+desPin);

//		String track2Data="6222021001086720528d49121209499991227";
//		String trkKey="FCEC16E3CC524B9D380FCCC34E40F502";
//		String deStrack2Data = encryptStanderTranck(trkKey,track2Data);
//		log.debug("deStrack2Data = "+deStrack2Data);
//
//	}
	
//	public static void main(String args[]){
//		String s1 = "明文数据";
//		System.out.println("明文数据:"+s1);
//		try {
//			String s2 = encode(s1);
//			System.out.println("密文数据:"+s2);
//			String s3 = decode(s2);
//			System.out.println("解密数据:"+s3);
//			
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//	}

}
